#include "gp_dj_ctl.h"

#include "sock_msg_ctl.h"
#include "gp_layout_map.h"
#include "stdio.h"
#include "string.h"
#include "../lua/action_msg.h"
#include "resource_manage.h"
#include <unistd.h>
#include "gp_subboard_ctl.h"
#include "../data_proc/board_data_proc.h"
#include "json/json.h"
#include <iostream>
#include <fstream>
#include <string>

//r->across area->
//ul->mm height
//3200<->x mm. 
const float coeffUlToSteps_DJ_Z = 50.1275;//deltaUl -> deltaHeight -> steps
const float coeffmmToSteps_DJ_Z = 629.92;//5.08mm<->3200 steps


const float coeffmmToSteps_DJ_Z_split = 629.92;//5.08mm<->3200 steps
const float coeffUlToSteps_DJ_Z_split = 0.764;//cross_area = 824.48

int g_isPurify = 0x11;

void djActFunc(void * paramIn,void * actResultOut)
{
    if(!paramIn || !actResultOut)
    {
        return;
    }
    printf("enter in djActFunc\n");
    act_msg_node * pstActMsg = (act_msg_node *)paramIn;
    int actSuccess = 0;
    char * ptrData = (char *)pstActMsg->paramData;
    
    if(pstActMsg->msgHead.actType == ACT_DJ_CLEAN_CTL)
    {
        djLiquidCtl djCleanParam;
        memset(&djCleanParam,0,sizeof(djLiquidCtl));
        djCleanParam.chanNum = pstActMsg->msgHead.paramType;

        if(djCleanParam.chanNum >= 88 + DJ_CLEAN_OUTER 
        && djCleanParam.chanNum <= 88 + DJ_CLEAN_ALL)
        {
            if(pstActMsg->msgHead.moduleType == MODULE_DJ_QPCR)
            {
                actSuccess = djCleanProcedure_q(djCleanParam.chanNum - 88);
            }
            else if(pstActMsg->msgHead.moduleType == MODULE_DJ_PURIFY)
            {
                actSuccess = djCleanProcedure_p(djCleanParam.chanNum - 88);
            }
        }
        else
        {
            if(pstActMsg->msgHead.moduleType == MODULE_DJ_QPCR)
            {
                djCleanParam.chanNum += 16;
            }
            int isOpen = 0;
            memcpy(&isOpen,ptrData,sizeof(int));
            djCleanParam.paramType = isOpen;

            actSuccess = djCleanCtl(&djCleanParam,SYSCTL_LIQUID,1000);
        }
    }
    else if(pstActMsg->msgHead.actType == ACT_SUCK_LIQUID)
    {
        suck_param stSuckParam;
        memset(&stSuckParam,0,sizeof(suck_param));
        int convertRet = djconvertSuckParam(pstActMsg,&stSuckParam);

        if(convertRet == 1)
        {

            location_layout stLayoutData;
            int isPurify = 0x11;
            memcpy(&stLayoutData,pstActMsg->paramData,sizeof(location_layout));

                
            if(pstActMsg->msgHead.moduleType == MODULE_DJ_QPCR)
            {
                isPurify = 0;
            }
            else if(stLayoutData.location_type == DJ_PURIFY_SPLIT )
            {
                isPurify = 0x01;
            }
            if(pstActMsg->msgHead.moduleType == MODULE_DJ_PURIFY)
            {
                g_isPurify = isPurify;
            }
            actSuccess = dj_suck(&stSuckParam,isPurify);

        }
        else
        {
            actSuccess = 0;
        }
    }
    else if(pstActMsg->msgHead.actType == ACT_SINGLE_MOVE)
    {
        if(pstActMsg->msgHead.paramType == PARAM_AXIS_MOVE_STEPS)
        {
            int component = 0;
            char * pData = (char *)(pstActMsg->paramData);
            memcpy(&component,pData,sizeof(int));

            pData += sizeof(int);

            int steps = 0;
            memcpy(&steps,pData,sizeof(int));

            int sidArr[7] = {SID_DJP_X,SID_DJP_Y,SID_DJP_Z,0,0,SID_DJP_PUMP_BIG,SID_DJP_PUMP_SMALL};
            
            if(pstActMsg->msgHead.moduleType == MODULE_DJ_QPCR)
            {
                int sidArrQpcr[7] = {SID_DJQ_X,SID_DJQ_Y,SID_DJQ_Z,SID_DJQ_JAWZ,SID_DJQ_JAW,SID_DJQ_PUMP,0};
                memcpy(sidArr,sidArrQpcr,sizeof(int)*7);
            }

            if(component<0 || component>=7)
            {
                actSuccess = 0;
            }
            else if(sidArr[component] == 0)
            {
                actSuccess = 0;
            }

            else
            {
                move_param moveParam;
                moveParam.pos = steps;
                moveParam.speed = 20000;
                moveParam.inc_speed = 80000;
                moveParam.dec_speed = 80000;
                moveParam.sid = sidArr[component];
                actSuccess = uimMoveAct_multi(&moveParam,1,20000);
            }
        }
                

    }
    else if(pstActMsg->msgHead.actType == ACT_SPIT_LIQUID)
    {
        tecan_liquid_param stSpitParam;
        memset(&stSpitParam,0,sizeof(suck_param));
        int convertRet = djconvertSpitParam(pstActMsg,&stSpitParam);

        if(convertRet == 1)
        {
            location_layout stLayoutData;
            int isPurify = 0x11;
            memcpy(&stLayoutData,pstActMsg->paramData,sizeof(location_layout));

                
            if(pstActMsg->msgHead.moduleType == MODULE_DJ_QPCR)
            {
                isPurify = 0;
            }
            else
            {
                isPurify = g_isPurify;
            }

            actSuccess = dj_spit_once(&stSpitParam,isPurify,1);
        }
        else
        {
            actSuccess = 0;
        }
    }
    else if(ACT_SPIT_LIQUID_MULTI == pstActMsg->msgHead.actType)
    {
        tecan_liquid_param stSpitParam;
        memset(&stSpitParam,0,sizeof(suck_param));
        location_layout stLayoutData;
        int convertRet = djconvertSpitParam_multi(pstActMsg->msgHead.moduleType,pstActMsg,&stSpitParam,&stLayoutData);

        if(convertRet == 1)
        {
            
            int isPurify = 0x11;
            if(pstActMsg->msgHead.moduleType == MODULE_DJ_QPCR)
            {
                isPurify = 0;
            }
            else
            {
                // if(stSpitParam.quantity >= 50)
                // {
                //     isPurify = 0x01;
                // }
                // else
                // {
                //     isPurify = 0x11;
                // }
                isPurify = g_isPurify;
            }
            
            char * spitHoles = (char *)pstActMsg->paramData;
            spitHoles += sizeof(location_layout);
            spitHoles += 4* sizeof(int);

            int dataLen = pstActMsg->msgHead.paramLen - sizeof(location_layout) - 3* sizeof(int);
            actSuccess = dj_spit_multi(&stSpitParam,&stLayoutData,spitHoles,dataLen,isPurify);
        }
        else
        {
            actSuccess = 0;
        }
    }
    else if(ACT_SINGLE_INIT == pstActMsg->msgHead.actType)
    {
       int component = 0;
       char * pData = (char *)(pstActMsg->paramData);
       memcpy(&component,pData,sizeof(int));

       int sidArr[7] = {SID_DJP_X,SID_DJP_Y,SID_DJP_Z,0,0,SID_DJP_PUMP_BIG,SID_DJP_PUMP_SMALL};
       
       if(pstActMsg->msgHead.moduleType == MODULE_DJ_QPCR)
       {
           int sidArrQpcr[7] = {SID_DJQ_X,SID_DJQ_Y,SID_DJQ_Z,SID_DJQ_JAWZ,SID_DJQ_JAW,SID_DJQ_PUMP,0};
           memcpy(sidArr,sidArrQpcr,sizeof(int)*7);
       }

       if(component<0 || component>=7)
       {
           actSuccess = 0;
       }
       else if(sidArr[component] == 0)
       {
           actSuccess = 0;
       }

       else if(MT_PUMP == component && pstActMsg->msgHead.moduleType == MODULE_DJ_PURIFY)
       {
           actSuccess = dj_purify_pump_init();
       }
       else
       {
           move_param moveParam;
           moveParam.pos = 0;
           moveParam.speed = 20000;
           moveParam.inc_speed = 80000;
           moveParam.dec_speed = 80000;
           moveParam.sid = sidArr[component];
           actSuccess = uimInitAct_multi(&moveParam,1,20000);
       }
    } 
    else if(ACT_MODULE_INIT == pstActMsg->msgHead.actType)
    {
        int isPurify = 1;
        if(pstActMsg->msgHead.moduleType == MODULE_DJ_QPCR)
        {
           isPurify = 0; 
        }
        actSuccess = dj_module_init(isPurify);
    }
    else if(ACT_PARRAL_MOVE == pstActMsg->msgHead.actType)
    {
        int isPurify = 1;
        if(pstActMsg->msgHead.moduleType == MODULE_DJ_QPCR)
        {
           isPurify = 0; 
        }

        location_layout locLayout;
        memcpy(&locLayout,((char*)pstActMsg->paramData) + sizeof(int),sizeof(location_layout));
        printf("location_type:%d,mx:%d,my:%d,ix:%d,iy:%d\n",
        locLayout.location_type,
        locLayout.indexX,
        locLayout.indexY,
        locLayout.column_x,
        locLayout.row_y);

        actSuccess = dj_module_move(&locLayout,isPurify);

    } 
    else if(ACT_SUCK1_SPITM == pstActMsg->msgHead.actType)
    {
        //1,suck param convert and suck here.
        suck_param stSuckParam;
        memset(&stSuckParam,0,sizeof(suck_param));
        int convertRet = djconvertSuckParam(pstActMsg,&stSuckParam);
        char * pData = (char *)pstActMsg->paramData;
        location_layout stLayoutData;
        int isPurify = 0x11;
        memcpy(&stLayoutData,pData,sizeof(location_layout));
        if(convertRet == 1)
        {
            
            if(pstActMsg->msgHead.moduleType == MODULE_DJ_QPCR)
            {
                isPurify = 0;
            }
            else if(stLayoutData.location_type == DJ_PURIFY_SPLIT )
            {
                isPurify = 0x01;
            }
            actSuccess = dj_suck(&stSuckParam,isPurify);
        }
        else
        {
            actSuccess = 0;
        }
        
        if(actSuccess == 1)
        {
            //2,spit param convert and spit here.
            tecan_liquid_param spitParam;
            location_layout locSpitFist;
            memset(&locSpitFist,0,sizeof(location_layout));
            memset(&spitParam,0,sizeof(tecan_liquid_param));
            pData += sizeof(location_layout) + sizeof(int)*4;//drop the suck param
            actSuccess = djconvertSpitParam_multi(pstActMsg->msgHead.moduleType,
            pData,&spitParam,&locSpitFist);

            if(actSuccess!=1)
            {
                actSuccess = 0;            
            }
            else
            {
                pData += sizeof(location_layout) + sizeof(int)*4;
                
                int SpitDataLen = pstActMsg->msgHead.paramLen - sizeof(location_layout)*2 - sizeof(int)*8;
                printf("in dj ACT_SUCK1_SPITM,SpitDataLen:%d\n",SpitDataLen);
                actSuccess = dj_spit_multi(&spitParam,&locSpitFist,pData,SpitDataLen,isPurify);
            }
        }

        

    }  
    else if(ACT_JAW_TRANS == pstActMsg->msgHead.actType)
    {
        printf("msg data len:%d,2layout len:%d\n",
        pstActMsg->msgHead.paramLen,
        2*sizeof(location_layout));


        actSuccess = djQ_transBoard(pstActMsg->paramData);
    }
    else if(ACT_PLUNGER_PUMP == pstActMsg->msgHead.actType)
    {
        printf("ACT_PLUNGER_PUMP,\n");
        if(PARAM_AXIS_MOVE_POS == pstActMsg->msgHead.paramType)
        {
            int component = 0;
            char * ptrData = (char *)pstActMsg->paramData;

            memcpy(&component,ptrData,sizeof(int));
            ptrData += sizeof(int);

            location_layout locLayout;
            memcpy(&locLayout,ptrData,sizeof(location_layout));

            int pumpType = DJ_PUMP_QPCR;

            if(pstActMsg->msgHead.moduleType == MODULE_DJ_PURIFY)
            {
                if(component == MT_PUMP)
                {
                    pumpType = DJ_PUMP_PURIFY_BIG;
                }
                else if(component == MT_PUMP_SMALL)
                {
                    pumpType = DJ_PUMP_PURIFY_SMALL;
                }                
            }

            if(component == MT_PUMP || component == MT_PUMP_SMALL)
            {
                int isSuck = 1;
                int suckvolume = locLayout.column_x;
                if(suckvolume < 0)
                {
                    isSuck = 0;
                    suckvolume = 0 - suckvolume;
                }
                actSuccess = dj_pump_ctl(isSuck, suckvolume, pumpType);
            }
        }
    }

    msgAckSock * pstResult = (msgAckSock *)actResultOut;

    if(!actSuccess)
    {
        pstResult->status = 1;
    }
    else
    {
        pstResult->status = 0;
    }
}

void getDjpPvCtlParam(Json::Value & jsonValueIn, djLiquidCtl * paramOut,int * numOut);

void getDjpEleCtlParam(Json::Value & jsonValueIn, move_param * paramOut,int * numOut);

int djCleanProcedure_p(int partIn)
{
    Json::Reader reader;
    Json::Value root;
    int ret = 0;

    const char * dj_p_json_all = "/mnt/nandflash/apps/config/dj_p_clean.json";

    const char * dj_p_json_in = "/mnt/nandflash/apps/config/dj_p_clean_in.json";

    const char * dj_p_json_out = "/mnt/nandflash/apps/config/dj_p_clean_out.json";

    const char * dj_p_json = NULL;

    if(partIn == DJ_CLEAN_OUTER)
    {
       dj_p_json =  dj_p_json_out;
    }
    else if(partIn == DJ_CLEAN_INNER)
    {
       dj_p_json =  dj_p_json_in;        
    }
    else
    {
       dj_p_json = dj_p_json_all;
    }
 
    //从文件中读取，保证当前文件有test.json文件
    std::ifstream in;//(configFiles_json[fileId], std::ios::binary);


    in.open(dj_p_json, std::ios::binary);
    
    
    if( !in.is_open() )
    {
        std::cout << "Error opening file,"<<dj_p_json<<std::endl;
        ret = -1;
        return ret; 
    }

    reader.parse(in,root);
 
    
    if(root.empty())
    {
        std::cout << "Error parse json content\n";
        root.clear();
        in.close();
        ret = -2;
        return ret;
    }

    if(root["dj_p"].empty())
    {
        std::cout << "Error dj p clean json content\n"; 
        root.clear();
        in.close();
        ret = -3;
        return ret;
    }
    
    Json::Value & nodeDjPurify = root["dj_p"];
    
    //std::vector<std::string> namesActions = nodeDjPurify.size();

    int totalSteps = nodeDjPurify.size();//namesActions.size();
    int indexStep = 0;
    move_param moveParamArr[MAX_PARALL_ACT];
    djLiquidCtl pvCtlParamArr[MAX_PARALL_ACT];
    char strStep[32] = {0};

    int actSuccess = 0;
    for(indexStep=0;indexStep<totalSteps;indexStep++)
    {
        //strStep = std::string("step") + std::to_string(indexStep+1);
        sprintf(strStep,"%s%d","step",indexStep+1);
        if(nodeDjPurify[strStep].empty())
        {
            ret = (indexStep+1);
            break;
        }

        Json::Value & action = nodeDjPurify[strStep];

        if(action["type"].empty())
        {
            std::cout<<"get action type failed"<< std::endl;
            ret = (indexStep+1);
            break;
        }

        std::string strActType = action["type"].asString();
        int actParamType = -1;
        if(action["type"].asString().compare("electl")==0)
        {
            actParamType = PARAM_ACT_ELE_CTL;
        }
        else if(action["type"].asString().compare("pvctl")==0)
        {
            actParamType = PARAM_ACT_PV_CTL;
        }

        if(actParamType == -1)
        {
            std::cout<<"action type is invalid"<< std::endl;
            ret = (indexStep+1);
            break;
        }

        int numParam = 0;
        int prewait_ms = 0;
        if(!action["pre_wait"].empty())
        {
            prewait_ms = action["pre_wait"].asInt();
        }

        if(actParamType == PARAM_ACT_ELE_CTL)
        {
            printf("----step:%d,ele ctl,prewait:%dms\n",indexStep+1,prewait_ms);
            getDjpEleCtlParam(action["electl"], moveParamArr,&numParam);
            for(int i=0;i<numParam;i++)
            {
                printf("sid:%d,pos:%d, v=%d,acc:%d,dec:%d\n",
                (moveParamArr+i)->sid,(moveParamArr+i)->pos,
                (moveParamArr+i)->speed,(moveParamArr+i)->inc_speed,
                (moveParamArr+i)->dec_speed);
            }
            if(numParam>0)
            {
                 if(prewait_ms>0)
                   {
                       usleep(1000*prewait_ms);
                   }
                actSuccess = uimMoveAct_multi(moveParamArr,numParam,20000);
            }           
            
        }
        else
        {
            printf("----step:%d,pv ctl,prewait:%dms\n",indexStep+1,prewait_ms);
            getDjpPvCtlParam(action["pvctl"], pvCtlParamArr,&numParam);
            printf("chan:%d,open:%d\n",pvCtlParamArr->chanNum,pvCtlParamArr->paramType);
            if(prewait_ms>0)
              {
                usleep(1000*prewait_ms);
              }            
            actSuccess = djCleanCtl(pvCtlParamArr,SYSCTL_LIQUID,1000);
        }               

    }

    root.clear();
    in.close();

    //printf("dj_p_clean, actSuccess:%d\n",actSuccess);

    ret = actSuccess;

    return ret;

}

void getOneEleCtlParam(std::vector<std::string>& strArrIn,Json::Value & jsonValueIn,move_param * moveParamOut)
{
    //std::vector<std::string> strArrInJson = jsonValueIn.getMemberNames();
    // int numStrEleCtl = 5;
    // std::vector<std::string> strArrEleCtl(numStrEleCtl);
    // strArrEleCtl[0] = "ele";
    // strArrEleCtl[1] = "speed";
    // strArrEleCtl[2] = "acc";
    // strArrEleCtl[3] = "dec";
    // strArrEleCtl[4] = "position";

    std::vector<std::string>::iterator itStrMotor = strArrIn.begin();
    int indexId = 0;

    moveParamOut->sid = 255;

    Json::Value & valueEle = jsonValueIn["ele"];
    Json::Value & valueSpeed = jsonValueIn["speed"];

    Json::Value & valueAcc = jsonValueIn["acc"];
    Json::Value & valueDec = jsonValueIn["dec"];
    Json::Value & valuePos = jsonValueIn["position"];


    if(!valueEle.empty())
    {
        std::string strMotorInJson = valueEle.asString();
        //std::cout<<"elename:"<<strMotorInJson<<std::endl;
        while(itStrMotor!=strArrIn.end())
        {
            if(itStrMotor->compare(strMotorInJson)==0)
            {
                //std::cout<<"set sid to: "<<indexId<<std::endl;
                moveParamOut->sid = indexId;
                break;
            }
            itStrMotor++;
            indexId++;
        }

        if(moveParamOut->sid == 255)
        {
            std::cout<<"ele name is not valid,"<<valueEle.asString()<<std::endl;
        }
    }

    if(!valueSpeed.empty())
    {
       moveParamOut->speed =  valueSpeed.asInt();
    }

    if(!valueAcc.empty())
    {
       moveParamOut->inc_speed =  valueAcc.asInt();
    }

    if(!valueDec.empty())
    {
       moveParamOut->dec_speed =  valueDec.asInt();
    }

    if(!valuePos.empty())
    {
       moveParamOut->pos =  valuePos.asInt();
    }

}

void getDjpEleCtlParam(Json::Value & jsonValueIn, move_param * paramOut,int * numOut)
{
    int numMotorDjP = 5;
    std::vector<std::string> strArrDjp(numMotorDjP);
    strArrDjp[0] = "dj_p_x";
    strArrDjp[1] = "dj_p_y";
    strArrDjp[2] = "dj_p_z";
    strArrDjp[3] = "dj_p_pump_big";
    strArrDjp[4] = "dj_p_pump_small";


    std::vector<int> sidArr(numMotorDjP);
    sidArr[0] = 29;
    sidArr[1] = 30;
    sidArr[2] = 31;
    sidArr[3] = 44;
    sidArr[4] = 45;
    int motorIndex = 0;

    if(jsonValueIn.isObject())
    {
        *numOut = 1;
        getOneEleCtlParam(strArrDjp,jsonValueIn,paramOut);
        
        motorIndex = paramOut->sid;
        if(motorIndex>=0&&numMotorDjP>motorIndex)
        {
            paramOut->sid = sidArr[motorIndex];
        }
        

    }
    else if(jsonValueIn.isArray())
    {
        *numOut = jsonValueIn.size();
        int i = 0;
        for(i=0;i<(*numOut);i++)
        {
            getOneEleCtlParam(strArrDjp,jsonValueIn[i],paramOut+i);
        
            motorIndex = (paramOut+i)->sid;
            if(motorIndex>=0&&numMotorDjP>motorIndex)
            {
                (paramOut+i)->sid = sidArr[motorIndex];
            }
            

            if(i>=MAX_PARALL_ACT)
            {//MAX_PARALL_ACT
                break;
            }
        }
    }

}

void getOnePvCtlParam(std::vector<std::string>& strArrIn,Json::Value & jsonValueIn,djLiquidCtl * pvParamOut)
{
    //std::vector<std::string> strArrInJson = jsonValueIn.getMemberNames();
    int numStrEleCtl = 2;
    std::vector<std::string> strArrEleCtl(numStrEleCtl);
    strArrEleCtl[0] = "ele";
    strArrEleCtl[1] = "openorclose";


    std::vector<std::string>::iterator itStrMotor = strArrIn.begin();
    int indexId = 0;

    pvParamOut->chanNum = 255;

    Json::Value & valueEle = jsonValueIn["ele"];
    Json::Value & valueOpen = jsonValueIn["openorclose"];

    if(!valueEle.empty())
    {
        std::string strMotorInJson = valueEle.asString();
        while(itStrMotor!=strArrIn.end())
        {
            if(itStrMotor->compare(strMotorInJson)==0)
            {
                pvParamOut->chanNum = indexId;
                break;
            }
            itStrMotor++;
            indexId++;
        }
    }

    if(pvParamOut->chanNum == 255)
    {
        std::cout<<"ele name is invalid"<<std::endl;
    }

    if(!valueOpen.empty())
    {
        pvParamOut->paramType = valueOpen.asInt();
    }
}

void getDjpPvCtlParam(Json::Value & jsonValueIn, djLiquidCtl * paramOut,int * numOut)
{
    int numMotorDjP = 8;
    std::vector<std::string> strArrDjp(numMotorDjP);
    strArrDjp[0] = "out_p";
    strArrDjp[1] = "in_p";
    strArrDjp[2] = "in_v_big";
    strArrDjp[3] = "waste_p";
    strArrDjp[4] = "waste_v";
    strArrDjp[5] = "in_v_small";
    strArrDjp[6] = "reserve_p";
    strArrDjp[7] = "mag_waste_p";


    std::vector<int> chanArr(numMotorDjP);
    chanArr[0] = 0;
    chanArr[1] = 1;
    chanArr[2] = 2;
    chanArr[3] = 3;
    chanArr[4] = 4;
    chanArr[5] = 5;
    chanArr[6] = 16 + 5;
    chanArr[7] = 16 + 3;
    int motorIndex = 0;

    if(jsonValueIn.isObject())
    {
        *numOut = 1;
        getOnePvCtlParam(strArrDjp,jsonValueIn,paramOut);
        
        motorIndex = paramOut->chanNum;
        paramOut->chanNum = chanArr[motorIndex];

    }
    // else if(jsonValueIn.isArray())
    // {
    //     *numOut = jsonValueIn.size();
    //     int i = 0;
    //     for(i=0;i<(*numOut);i++)
    //     {
    //         getOneEleCtlParam(strArrDjp,jsonValueIn,&(paramOut+i)->moveParam);
        
    //         motorIndex = paramOut->moveParam.sid;
    //         paramOut->moveParam.sid = chanArr[motorIndex];

    //         if(i>=MAX_PARALL_ACT)
    //         {//MAX_PARALL_ACT
    //             break;
    //         }
    //     }
    // }

}

void getDjqEleCtlParam(Json::Value & jsonValueIn, move_param * paramOut,int * numOut)
{
    int numMotorDjq = 6;
    std::vector<std::string> strArrDjq(numMotorDjq);
    strArrDjq[0] = "dj_q_x";
    strArrDjq[1] = "dj_q_y";
    strArrDjq[2] = "dj_q_z";
    strArrDjq[3] = "dj_q_pump";
    strArrDjq[4] = "dj_q_jaw";
    strArrDjq[5] = "dj_q_jawz";



    std::vector<int> sidArr(numMotorDjq);
    sidArr[0] = 12;
    sidArr[1] = 17;
    sidArr[2] = 28;
    sidArr[3] = 46;
    sidArr[4] = 19;
    sidArr[5] = 18;

    int motorIndex = 0;

    if(jsonValueIn.isObject())
    {
        *numOut = 1;
        getOneEleCtlParam(strArrDjq,jsonValueIn,paramOut);
        
        motorIndex = paramOut->sid;
        if(motorIndex>=0&&numMotorDjq>motorIndex)
        {
            paramOut->sid = sidArr[motorIndex];
        }       

    }
    else if(jsonValueIn.isArray())
    {
        *numOut = jsonValueIn.size();
        int i = 0;
        for(i=0;i<(*numOut);i++)
        {
            getOneEleCtlParam(strArrDjq,jsonValueIn[i],paramOut+i);
        
            motorIndex = (paramOut+i)->sid;
            if(motorIndex>=0&&numMotorDjq>motorIndex)
            {
                (paramOut+i)->sid = sidArr[motorIndex];
            }
            

            if(i>=MAX_PARALL_ACT)
            {//MAX_PARALL_ACT
                break;
            }
        }
    }

}

void getDjqPvCtlParam(Json::Value & jsonValueIn, djLiquidCtl * paramOut,int * numOut)
{
    int numMotorDjq = 7;
    std::vector<std::string> strArrDjq(numMotorDjq);
    strArrDjq[0] = "out_p";
    strArrDjq[1] = "in_p";
    strArrDjq[2] = "in_v";
    strArrDjq[3] = "waste_p";
    strArrDjq[4] = "waste_v";
    strArrDjq[5] = "reserved_p";
    strArrDjq[6] = "mag_waste_p";


    std::vector<int> chanArr(numMotorDjq);
    chanArr[0] = 0;
    chanArr[1] = 1;
    chanArr[2] = 2;
    chanArr[3] = 3;
    chanArr[4] = 4;
    chanArr[5] = 5;
    chanArr[6] = 3;

    int motorIndex = 0;

    if(jsonValueIn.isObject())
    {
        *numOut = 1;
        getOnePvCtlParam(strArrDjq,jsonValueIn,paramOut);
        
        motorIndex = paramOut->chanNum;

        if(motorIndex==3)
        {
            paramOut->chanNum = chanArr[motorIndex];  
        }
        else
        {
            paramOut->chanNum = chanArr[motorIndex] + 16;
        }        

    }
    // else if(jsonValueIn.isArray())
    // {
    //     *numOut = jsonValueIn.size();
    //     int i = 0;
    //     for(i=0;i<(*numOut);i++)
    //     {
    //         getOneEleCtlParam(strArrDjp,jsonValueIn,&(paramOut+i)->moveParam);
        
    //         motorIndex = paramOut->moveParam.sid;
    //         paramOut->moveParam.sid = chanArr[motorIndex];

    //         if(i>=MAX_PARALL_ACT)
    //         {//MAX_PARALL_ACT
    //             break;
    //         }
    //     }
    // }

}

int djCleanProcedure_q(int partIn)
{
    Json::Reader reader;
    Json::Value root;
    int ret = 0;

    const char * dj_q_json_all = "/mnt/nandflash/apps/config/dj_q_clean.json";

    const char * dj_q_json_in = "/mnt/nandflash/apps/config/dj_q_clean_in.json";

    const char * dj_q_json_out = "/mnt/nandflash/apps/config/dj_q_clean_out.json";

    const char * dj_q_json = NULL;

    if(partIn == DJ_CLEAN_OUTER)
    {
       dj_q_json =  dj_q_json_out;
    }
    else if(partIn == DJ_CLEAN_INNER)
    {
       dj_q_json =  dj_q_json_in;        
    }
    else
    {
       dj_q_json = dj_q_json_all;
    }
 
    //从文件中读取，保证当前文件有test.json文件
    std::ifstream in;//(configFiles_json[fileId], std::ios::binary);


    in.open(dj_q_json, std::ios::binary);
    
    
    if( !in.is_open() )
    {
        std::cout << "Error opening file,"<<dj_q_json<<std::endl;
        ret = -1;
        return ret; 
    }

    reader.parse(in,root);
 
    
    if(root.empty())
    {
        std::cout << "Error parse json content\n";
        root.clear();
        in.close();
        ret = -2;
        return ret;
    }

    if(root["dj_q"].empty())
    {
        std::cout << "Error dj p clean json content\n"; 
        root.clear();
        in.close();
        ret = -3;
        return ret;
    }
    
    Json::Value & nodeDjQpcr = root["dj_q"];
    
    //std::vector<std::string> namesActions = nodeDjPurify.size();

    int totalSteps = nodeDjQpcr.size();//namesActions.size();
    int indexStep = 0;
    move_param moveParamArr[MAX_PARALL_ACT];
    djLiquidCtl pvCtlParamArr[MAX_PARALL_ACT];
    char strStep[32] = {0};

    int actSuccess = 0;
    for(indexStep=0;indexStep<totalSteps;indexStep++)
    {
        //strStep = std::string("step") + std::to_string(indexStep+1);
        sprintf(strStep,"%s%d","step",indexStep+1);
        if(nodeDjQpcr[strStep].empty())
        {
            ret = (indexStep+1);
            break;
        }

        Json::Value & action = nodeDjQpcr[strStep];

        if(action["type"].empty())
        {
            std::cout<<"get action type failed"<< std::endl;
            ret = (indexStep+1);
            break;
        }

        std::string strActType = action["type"].asString();
        int actParamType = -1;
        if(action["type"].asString().compare("electl")==0)
        {
            actParamType = PARAM_ACT_ELE_CTL;
        }
        else if(action["type"].asString().compare("pvctl")==0)
        {
            actParamType = PARAM_ACT_PV_CTL;
        }

        if(actParamType == -1)
        {
            std::cout<<"action type is invalid"<< std::endl;
            ret = (indexStep+1);
            break;
        }

        int numParam = 0;
        int prewait_ms = 0;
        if(!action["pre_wait"].empty())
        {
            prewait_ms = action["pre_wait"].asInt();
        }

        if(actParamType == PARAM_ACT_ELE_CTL)
        {
            printf("----step:%d,ele ctl,prewait:%dms\n",indexStep+1,prewait_ms);
            getDjqEleCtlParam(action["electl"], moveParamArr,&numParam);
            for(int i=0;i<numParam;i++)
            {
                printf("sid:%d,pos:%d, v=%d,acc:%d,dec:%d\n",
                (moveParamArr+i)->sid,(moveParamArr+i)->pos,
                (moveParamArr+i)->speed,(moveParamArr+i)->inc_speed,
                (moveParamArr+i)->dec_speed);
            }
            if(numParam>0)
            {
                 if(prewait_ms>0)
                   {
                       usleep(1000*prewait_ms);
                   }
                actSuccess = uimMoveAct_multi(moveParamArr,numParam,20000);
            }           
            
        }
        else
        {
            printf("----step:%d,pv ctl,prewait:%dms\n",indexStep+1,prewait_ms);
            getDjqPvCtlParam(action["pvctl"], pvCtlParamArr,&numParam);
            printf("chan:%d,open:%d\n",pvCtlParamArr->chanNum,pvCtlParamArr->paramType);
            if(prewait_ms>0)
              {
                usleep(1000*prewait_ms);
              }            
            actSuccess = djCleanCtl(pvCtlParamArr,SYSCTL_LIQUID,1000);
        }               

    }

    root.clear();
    in.close();

    ret = actSuccess;

    return ret;

}



int dj_suck(void * paramIn, int purifyCtlIn)
{
    suck_param * pstSuckParam = (suck_param *)paramIn;

    int actSuccess = 0;
    int sidx = SID_DJQ_X;
    int sidy = SID_DJQ_Y;
    int sidz = SID_DJQ_Z;
    int sidPump = SID_DJQ_PUMP;

    int z_tube_mouth = 0;
    float coeffUlToSteps = 12.8;//32000steps<-->2500ul for pump
    
    float coeffU2H_Z = coeffUlToSteps_DJ_Z;

    if(pstSuckParam->quantity <= 0)
    {
        printf("in dj_suck, suck voluem is 0 failed\n");
        return 0;
    }
    
    if(purifyCtlIn)
    {
        sidx = SID_DJP_X;
        sidy = SID_DJP_Y;
        sidz = SID_DJP_Z;
        if(purifyCtlIn&0x10)
        {
            sidPump = SID_DJP_PUMP_SMALL;
            coeffUlToSteps = 128;//32000steps<-->250ul
            coeffU2H_Z = coeffUlToSteps_DJ_Z;
        }
        else
        {
            sidPump = SID_DJP_PUMP_BIG;
            coeffUlToSteps = 6.4;
            coeffU2H_Z = coeffUlToSteps_DJ_Z_split;
        }
         //********************88
        //change the switch here.
    }
    //1, dj niddle go down to tube mouth    
    move_param stDjMove[2];
    stDjMove[0].sid = sidz;
    stDjMove[0].pos = pstSuckParam->posPre; //dj go down to tube mouth
    stDjMove[0].dec_speed = 80000;
    stDjMove[0].inc_speed = 80000;
    stDjMove[0].speed = 20000;

    actSuccess = uimMoveAct_multi(stDjMove,1,20000);
    if(actSuccess!=1)
    {
        printf("in dj_suck, z go to pre pos failed\n");
        return 0;
    }
    
    //2,suck air 1
    stDjMove[0].sid = sidPump;
    stDjMove[0].pos = pstSuckParam->air1Quan * coeffUlToSteps; //dj go down to tube mouth
    stDjMove[0].speed = pstSuckParam->speedSuckAir1 * coeffUlToSteps;
    stDjMove[0].dec_speed = stDjMove[0].speed * 4;
    stDjMove[0].inc_speed = stDjMove[0].speed * 4;
    stDjMove[0].dir = 1; //move away origin point
      
    actSuccess = uimMoveAct_multi_relative(stDjMove,1,20000);
    if(actSuccess!=1)
    {
        printf("in dj_suck, suck air1 failed\n");
        return 0;
    }

    //3, z go  down to suck pos    
    stDjMove[0].sid = sidz;
    //this is the variable calculated through the remain liquid
    stDjMove[0].pos = pstSuckParam->posPost; 
    stDjMove[0].dec_speed = 80000;
    stDjMove[0].inc_speed = 80000;
    stDjMove[0].speed = 20000;

    actSuccess = uimMoveAct_multi(stDjMove,1,20000);
    if(actSuccess!=1)
    {
        printf("in dj_suck, z go to liquid face failed\n");
        return 0;
    }

    printf("in dj_suck, z go to liquid face:%d ok\n",pstSuckParam->posPost);

    //4, suck and z go down at the same time
    // float height_before = 0;
    // float height_after = 0;
    
    // int containerTypeT = getContainerType_Dj(locTypeIn);

    int deltaStepsZ = pstSuckParam->stepBelow;
    if(deltaStepsZ <= 0)
    {
        deltaStepsZ = coeffU2H_Z * pstSuckParam->quantity;
    }



    stDjMove[0].sid = sidz;    //
    stDjMove[0].pos = deltaStepsZ;
    stDjMove[0].speed = deltaStepsZ/pstSuckParam->quantity*pstSuckParam->speedSuck;
    stDjMove[0].dec_speed = stDjMove[0].speed * 4;
    stDjMove[0].inc_speed = stDjMove[0].speed * 4;
    stDjMove[0].dir = 1; //go away origin

    stDjMove[1].sid = sidPump;    //
    stDjMove[1].pos = coeffUlToSteps * (pstSuckParam->quantity + pstSuckParam->more);
    stDjMove[1].speed = pstSuckParam->speedSuck * coeffUlToSteps;
    stDjMove[1].dec_speed = stDjMove[1].speed * 4;
    stDjMove[1].inc_speed = stDjMove[1].speed * 4;
    stDjMove[1].dir = 1; //go away origin

    printf("steps deltaz:%d, volume%f,coeff:%f\n",stDjMove[0].pos,pstSuckParam->quantity,coeffU2H_Z);
    actSuccess = uimMoveAct_multi_relative(stDjMove,2,20000);
    if(actSuccess!=1)
    {
        printf("in dj_suck, suck liquid failed\n");
        return 0;
    }

    if(pstSuckParam->delayAfterSuck > 0)
    {
        usleep(1000*pstSuckParam->delayAfterSuck);
    }
    //5, spit out back    
    stDjMove[0].sid = sidPump;
    stDjMove[0].pos = pstSuckParam->spitQuan * coeffUlToSteps; //dj go down to tube mouth
    stDjMove[0].speed = pstSuckParam->spitSpeed * coeffUlToSteps;
    stDjMove[0].dec_speed = stDjMove[0].speed * 4;
    stDjMove[0].inc_speed = stDjMove[0].speed * 4;
    stDjMove[0].dir = 0; //move toward origin point      
    actSuccess = uimMoveAct_multi_relative(stDjMove,1,20000);

    if(actSuccess!=1)
    {
        printf("in dj_suck, spit back failed\n");
        return 0;
    }

    
    if(pstSuckParam->delayAfterSpit > 0)
    {
        usleep(1000*pstSuckParam->delayAfterSpit);
    }
    //6, z go up to pre pos
    stDjMove[0].sid = sidz;
    stDjMove[0].pos = pstSuckParam->posPre; //dj go down to tube mouth
    stDjMove[0].dec_speed = 80000;
    stDjMove[0].inc_speed = 80000;
    stDjMove[0].speed = 20000;

    actSuccess = uimMoveAct_multi(stDjMove,1,20000); 

    if(actSuccess!=1)
    {
        printf("in dj_suck, z go back to tube mouth failed\n");
        return 0;
    }

    printf("in dj_suck, z goto pre:%d ok\n",pstSuckParam->posPre);

    //7,suck air2
    if(pstSuckParam->air2Quan > 0)
    {
        stDjMove[0].sid = sidPump;
        stDjMove[0].pos = pstSuckParam->air2Quan * coeffUlToSteps; //dj go down to tube mouth
        stDjMove[0].speed = pstSuckParam->speedSuckAir2 * coeffUlToSteps;
        stDjMove[0].dec_speed = stDjMove[0].speed * 4;
        stDjMove[0].inc_speed = stDjMove[0].speed * 4;
        stDjMove[0].dir = 1; //move away origin point      
        actSuccess = uimMoveAct_multi_relative(stDjMove,1,20000);

        if(actSuccess!=1)
        {
            printf("in dj_suck, suck air2 failed\n");
            return 0;
        }

        if(pstSuckParam->delayAfterSpit > 0)
        {
            usleep(1000*pstSuckParam->delayAfterSpit);
        }
    }

    

    //8, z go up to 0
    stDjMove[0].sid = sidz;
    stDjMove[0].pos = 0; //dj z goto 0
    stDjMove[0].dec_speed = 80000;
    stDjMove[0].inc_speed = 80000;
    stDjMove[0].speed = 20000;

    actSuccess = uimMoveAct_multi(stDjMove,1,20000);

    if(actSuccess!=1)
    {
        printf("in dj_suck, z go back to 0 failed\n");
        return 0;
    }

    return actSuccess;
}

const suck_ctl djSuckCtlParam[VISCOSITY_DUMMY] = 
{
    {
       .air1 = 10,
       .air2 = 5,
       .speedSuck = 100,
       .liquidMore = 5,
       .spitQuan = 4,
       .spitSpeed = 400,//400 ul/s
    },
    {
       .air1 = 6,
       .air2 = 6,
       .speedSuck = 90,
       .liquidMore = 5,
       .spitQuan = 4,
       .spitSpeed = 350,
    },
    {
       .air1 = 7,
       .air2 = 7,
       .speedSuck = 80,
       .liquidMore = 5,
       .spitQuan = 4,
       .spitSpeed = 300,
    }
};

int getContainerType_Dj(int locTypeIn)
{
    int ret = -1;

    switch(locTypeIn)
    {
       case DJ_QPCR_48HOLES:
       {
           ret = CONTAINER_PCR_BOARD;
       }
       break;
       case DJ_QPCR_REAGENT:
       {
           ret = CONTAINER_PCR_REAGENT;
       }
       break;
       case DJ_PURIFY_8HOLES_A:
       case DJ_PURIFY_8HOLES_B:
       {
           ret = CONTAINER_8TUBE;
       }
       break;
       case DJ_PURIFY_SPLIT:
       {
           ret = CONTAINER_PU_SPLIT;
       }
       break;
       case DJ_PURIFY_REAGENT:
       {
           ret = CONTAINER_PU_REAGENT1;
       }
       break;
       case DJ_PURIFY_MAG_SHAKE:
       {
           ret = CONTAINER_PU_REAGENT1;
       }
       break;

       default:
        break;
    }
    return ret;
}


int djconvertSuckParam(void * paramIn, void * paramOut)
{
    act_msg_node * pstActMsg = (act_msg_node *)paramIn;
    int actSuccess = 0;

    int isPurify = 0;

    //1, go to target location
    location_layout locLayout;
    location_axis locAxis;
    memcpy(&locLayout,(char*)pstActMsg->paramData,sizeof(location_layout));
    printf("in djconvertSuckParam, location_type:%d,mx:%d,my:%d,ix:%d,iy:%d\n",
    locLayout.location_type,
    locLayout.indexX,
    locLayout.indexY,
    locLayout.column_x,
    locLayout.row_y);

    int moduleLiquidType = DJ_PURIFY_LIQUID_TYPE;

    if(pstActMsg->msgHead.moduleType == MODULE_DJ_PURIFY)
    {
        isPurify = 1;
    }
    else if(pstActMsg->msgHead.moduleType == MODULE_DJ_QPCR)
    {
        isPurify = 0;
        moduleLiquidType = DJ_QPCR_LIQUID_TYPE;
    }
    else
    {
        printf("in djconvertSuckParam, module type is invalid\n");
        return 0;
    }
    CGpLayout * pstLayout = CGpLayout::get_instance();
    int convertRet = pstLayout->convertToAxisLoc(&locLayout,&locAxis);
    if(convertRet)
    {
        printf("djconvertSuckParam, convert location failed,errorNum:%d\n",convertRet);
    }
    else 
    {
        printf("x=%d,y=%d\n",locAxis.x,locAxis.y);

        actSuccess = djXY_Move(&locAxis,isPurify);
    }
    
    if(actSuccess!=1)
    {
        printf("in djconvertSuckParam, x,y go to target location failed\n");
        return 0;
    }
    int liquidType = VISCOSITY_LOW;
    int suckVolume = 0;
    char * pstDataBuff = ((char*)pstActMsg->paramData) + sizeof(location_layout);
    //|xylayout|liquidtype|suckVolume|isformulti|remainVolume
    memcpy(&liquidType,pstDataBuff,sizeof(int));
    
    //store the liquid type
    CResource_Manage  * pstResManage = getResourceManage();

    if(pstResManage)
    {
       pstResManage->set_curr_liquid_type( moduleLiquidType,liquidType); 

       if(isPurify)
       {
            if(locLayout.location_type == DJ_PURIFY_SPLIT)
            {
                pstResManage->set_purify_pump_type(PURIFY_PUMP_BIG);
            }
            else
            {
                pstResManage->set_purify_pump_type(PURIFY_PUMP_SMALL);
            }
            
       }
    }

    pstDataBuff += sizeof(int);
    memcpy(&suckVolume,pstDataBuff,sizeof(int));
    
    pstDataBuff += sizeof(int);
    int isForMulti = 0;
    memcpy(&isForMulti,pstDataBuff,sizeof(int));

    pstDataBuff += sizeof(int);

    int remainVolume = 0;
    memcpy(&remainVolume,pstDataBuff,sizeof(int));

    int volumeAir2 = djSuckCtlParam[liquidType].air2;

    // if(isForMulti)
    // {
    //     volumeAir2 = 0;
    // }
    printf("liquidType:%d,volume:%d, isForMulti:%d\n",liquidType,suckVolume,isForMulti);
    if(liquidType >= VISCOSITY_DUMMY || liquidType < VISCOSITY_LOW)
    {
        printf("in dp1_suck, liquidType is %d,change to VISCOSITY_LOW\n");
        liquidType = VISCOSITY_LOW;
    }
    dynamic_z z_height_pos;
    int zlocValid = pstLayout->getZloc(locLayout.location_type,&z_height_pos);
    if(!zlocValid)
    {
        printf("z location is not valid\n");
        return 0;
    }   
    
    printf("z tube mouth:%d,z max:%d\n",z_height_pos.z_tube_mouth,z_height_pos.z_max);

    int posPre = z_height_pos.z_tube_mouth;

    suck_param * pstSuckParam = (suck_param *)paramOut;
    
    //float liquid_height = 0;
    //convertRet = volumeToHeight(remainVolume,TUBE_BOTTOM_CONE,&liquid_height); 
    
    float coeffUlToStepsTemp = coeffUlToSteps_DJ_Z;
    float djSuckSpeed = djSuckCtlParam[liquidType].speedSuck;

    float djLiquidMore = djSuckCtlParam[liquidType].liquidMore;
    float djSpitBack = djSuckCtlParam[liquidType].spitQuan;
    if(locLayout.location_type == DJ_PURIFY_SPLIT)
    {
        coeffUlToStepsTemp =  coeffUlToSteps_DJ_Z_split;
        z_height_pos.z_tube_mouth += 8673;
        z_height_pos.z_max += 9900; 

        djSuckSpeed = 400;

        djLiquidMore = 25;
        djSpitBack = 5;
    }
    
    
    float heightMm = 0;

    int containerTypeDj = getContainerType_Dj(locLayout.location_type);
    
    if(containerTypeDj == -1)
    {
        printf("in djconvertSuckParam, get container type failed\n");
        return 0;
    }
    else
    {
        printf("containerType:%d\n",containerTypeDj);
    }
    

    int converHRet = volumeToHeight_en(remainVolume,containerTypeDj,&heightMm);
    if(converHRet != 0)
    {
        printf("in djconvertSuckParam, calc height through remainvolume failed\n");
        return 0;
    }
    int deltaHeightSteps =    heightMm*coeffmmToSteps_DJ_Z;

    printf("remainVolume:%d, delta steps:%d, heightMm:%f\n",remainVolume,deltaHeightSteps,heightMm);
    int liquidFaceSteps = z_height_pos.z_max - deltaHeightSteps;

    if(liquidFaceSteps<z_height_pos.z_tube_mouth || liquidFaceSteps > z_height_pos.z_max)
    {
        printf("djconvertSuckParam, liquid face height is invalid,liquidFaceSteps:%d,mouth:%d,z_max:%d\n",
        liquidFaceSteps,z_height_pos.z_tube_mouth,z_height_pos.z_max);
        return 0;
    }

    float heightAfterSuck = heightMm;
    converHRet = volumeToHeight_en(remainVolume-suckVolume,containerTypeDj,&heightAfterSuck);
    if(converHRet != 0)
    {
        printf("in djconvertSuckParam, calc height after sucking failed\n");
        return 0;
    }

    int deltaStepsZ = (heightMm - heightAfterSuck)*coeffmmToSteps_DJ_Z;
    
    printf("delta steps z:%d when sucking\n",deltaStepsZ);
    if(deltaStepsZ < 0 )
    {
       deltaStepsZ = 0; 
    }

    if(liquidFaceSteps + deltaStepsZ > z_height_pos.z_max)
    {
        deltaStepsZ = z_height_pos.z_max - liquidFaceSteps - 100;
    }

    suck_param tempSuckParam = {
        .posPre = posPre, // this should be change according to the ----
        .speedPre = 20000, // the speed go to previous position
        .air1Quan = djSuckCtlParam[liquidType].air1, // the air quantity before suck liquid
        .speedDetect = 210,//20mm/s / 0.009525 = 209.973// the speed of detecting liquid face
        .threshold = 9, // the threshold of detecting
        .stepBelow = deltaStepsZ,// for dj, this value used to setting the deltaz steps when sucking.
        .speedSuck = djSuckSpeed,// the suck speed
        .quantity = suckVolume, // the suck quantity
        .more = djLiquidMore, // the reduntant quantity
        .posMax = z_height_pos.z_max, //the max pos to go if no liquid ----this should be changed.
        .posPost = liquidFaceSteps, // this is calculated through the remain liquid volume.
        .speedPost = 210, // the speed to go to posPost,---equals to speedDetect
        .air2Quan = volumeAir2, // the air quantity after suck liquid    
        .spitQuan = djSpitBack, // spit back quantity
        .speedSuckAir1 = 50,//ul/s
        .delayAfterSuck = 1000, //ms
        .delayAfterSpit = 500, //ms
        .speedSuckAir2 = 50,//ul/s
        .spitSpeed = djSuckCtlParam[liquidType].spitSpeed,//inc/s
    };

    memcpy(pstSuckParam,&tempSuckParam,sizeof(suck_param));
    return 1;
}


int djXY_Move(void * paramIn, int isPurify)
{
    location_axis * pstLocAxis = (location_axis *)paramIn;
    int sidx = SID_DJQ_X;
    int sidy = SID_DJQ_Y;
    int sidz = SID_DJQ_Z;

    int sidjawz = SID_DJQ_JAWZ;

    int actPartNum = 2;

    if(isPurify)
    {
       sidx =  SID_DJP_X;
       sidy =  SID_DJP_Y;
       sidz =  SID_DJP_Z;
       actPartNum = 1;
    }

    move_param moveParam[3];
    moveParam[0].sid = sidz;
    moveParam[0].pos = 0;
    moveParam[0].dec_speed = 80000;
    moveParam[0].inc_speed = 80000;
    moveParam[0].speed = 20000;

    moveParam[1].sid = sidjawz;
    moveParam[1].pos = 0;
    moveParam[1].dec_speed = 80000;
    moveParam[1].inc_speed = 80000;
    moveParam[1].speed = 20000;

    int actSuccess = uimMoveAct_multi(moveParam, actPartNum, 20000);

    if(actSuccess != 1)
    {
        printf("dj z and go to 0 failed,actRet:%d\n",actSuccess);
        return actSuccess;
    }
    
    moveParam[0].sid = sidx;
    moveParam[0].pos = pstLocAxis->x;
    moveParam[0].dec_speed = 64000;
    moveParam[0].inc_speed = 64000;
    moveParam[0].speed = 16000;

    moveParam[1].sid = sidy;
    moveParam[1].pos = pstLocAxis->y;
    moveParam[1].dec_speed = 64000;
    moveParam[1].inc_speed = 64000;
    moveParam[1].speed = 16000;

    actSuccess = uimMoveAct_multi(moveParam, 2, 20000);

    return actSuccess;
}

int djXY_Move_withoutZup(void * paramIn, int isPurify)
{
    location_axis * pstLocAxis = (location_axis *)paramIn;
    int sidx = SID_DJQ_X;
    int sidy = SID_DJQ_Y;
    int sidz = SID_DJQ_Z;

    int sidjawz = SID_DJQ_JAWZ;

    int actPartNum = 2;
    int actSuccess = 0;

    if(isPurify)
    {
       sidx =  SID_DJP_X;
       sidy =  SID_DJP_Y;
       sidz =  SID_DJP_Z;
       actPartNum = 1;
    }

    move_param moveParam[3];
    
    moveParam[0].sid = sidx;
    moveParam[0].pos = pstLocAxis->x;
    moveParam[0].dec_speed = 64000;
    moveParam[0].inc_speed = 64000;
    moveParam[0].speed = 16000;

    moveParam[1].sid = sidy;
    moveParam[1].pos = pstLocAxis->y;
    moveParam[1].dec_speed = 64000;
    moveParam[1].inc_speed = 64000;
    moveParam[1].speed = 16000;

    actSuccess = uimMoveAct_multi(moveParam, 2, 20000);

    return actSuccess;
}

int dj_spit_once(void * paramIn, int purifyCtlIn, int zGoOrigin)
{
    int actSuccess = 0;
    int sidx = SID_DJQ_X;
    int sidy = SID_DJQ_Y;
    int sidz = SID_DJQ_Z;
    int sidPump = SID_DJQ_PUMP;

    int z_tube_mouth = 0;
    float coeffUlToSteps = 12;//32000steps<-->2500ul for pump
    if(purifyCtlIn)
    {
        sidx = SID_DJP_X;
        sidy = SID_DJP_Y;
        sidz = SID_DJP_Z;
        if(purifyCtlIn&0x10)
        {
            sidPump = SID_DJP_PUMP_SMALL;
            coeffUlToSteps = 120;//32000steps<-->250ul
        }
        else
        {
            sidPump = SID_DJP_PUMP_BIG;
            coeffUlToSteps = 6;
        }
         //********************88
        //change the switch here.
    }

    tecan_liquid_param * spitParam = (tecan_liquid_param * )paramIn;
    
    //1, z go to the pos after spit. 
    move_param stDjMove[2];
    stDjMove[0].sid = sidz;
    stDjMove[0].pos = spitParam->posPre; //dj go down to height of after spitting
    stDjMove[0].dec_speed = 80000;
    stDjMove[0].inc_speed = 80000;
    stDjMove[0].speed = 20000;

    actSuccess = uimMoveAct_multi(stDjMove,1,20000);
    if(actSuccess!=1)
    {
        printf("in dj_spit_once, z go to pre pos failed\n");
        return 0;
    }
    
    //2, spit out the air
    if(spitParam->quanSpitAir1 > 0)
    {
        stDjMove[0].sid = sidPump;
        stDjMove[0].pos = spitParam->quanSpitAir1 * coeffUlToSteps; //dj go down to height of after spitting
        stDjMove[0].speed = spitParam->speed*coeffUlToSteps;
        stDjMove[0].dec_speed = 4*stDjMove[0].speed;
        stDjMove[0].inc_speed = stDjMove[0].dec_speed;
        
        stDjMove[0].dir = 0; //go toward origin

        actSuccess = uimMoveAct_multi_relative(stDjMove,1,20000);
        if(actSuccess!=1)
        {
            printf("in dj_spit_once, spit out air1 failed\n");
            return 0;
        }
    }    
    //3, spit out the liquid
    stDjMove[0].sid = sidPump;
    stDjMove[0].pos = spitParam->quantity * coeffUlToSteps; //dj go down to height of after spitting
    if(sidPump == SID_DJP_PUMP_BIG)
    {
        stDjMove[0].speed = 400*coeffUlToSteps;
    }
    else
    {
        stDjMove[0].speed = spitParam->speed*coeffUlToSteps;
    }    

    stDjMove[0].dec_speed = 4*stDjMove[0].speed;
    stDjMove[0].inc_speed = stDjMove[0].dec_speed;
    
    stDjMove[0].dir = 0; //go toward origin

    printf("spit out %f ul\n",spitParam->quantity);

    actSuccess = uimMoveAct_multi_relative(stDjMove,1,20000);
    if(actSuccess!=1)
    {
        printf("in dj_spit_once, spit out liquid failed\n");
        return 0;
    }

    if(spitParam->delayAfterSpit > 0)
    {
        usleep(1000*spitParam->delayAfterSpit);
    }

    //4, z go up to tube mouth.
    stDjMove[0].sid = sidz;
    stDjMove[0].pos = spitParam->posPost; //dj go up to tube mouth
    stDjMove[0].speed = 20000;
    stDjMove[0].dec_speed = 80000;
    stDjMove[0].inc_speed = 80000;
    
    stDjMove[0].dir = 0; //go toward origin

    actSuccess = uimMoveAct_multi(stDjMove,1,20000);
    if(actSuccess!=1)
    {
        printf("in dj_spit_once, z go back up to tube mouth failed\n");
        return 0;
    }

    //5, suck back.
    if(spitParam->quanSuckBack>0.0001)
    {
        stDjMove[0].sid = sidPump;
        stDjMove[0].pos = spitParam->quanSuckBack*coeffUlToSteps; //dj go down to height of after spitting
        stDjMove[0].speed = spitParam->speedSuckBack * coeffUlToSteps;
        stDjMove[0].dec_speed = stDjMove[0].speed * 4;
        stDjMove[0].inc_speed = stDjMove[0].dec_speed;
        
        stDjMove[0].dir = 1; //go away origin

        actSuccess = uimMoveAct_multi_relative(stDjMove,1,20000);
        if(actSuccess!=1)
        {
            printf("in dj_spit_once, suck back failed\n");
            return 0;
        }
    }

    //6, z go up

    if(zGoOrigin)
    {
        stDjMove[0].sid = sidz;
        stDjMove[0].pos = 0; //dj go down to height of after spitting
        stDjMove[0].speed = 20000;
        stDjMove[0].dec_speed = 80000;
        stDjMove[0].inc_speed = 80000;
        
        stDjMove[0].dir = 0; //go toward origin

        actSuccess = uimMoveAct_multi(stDjMove,1,20000);
        if(actSuccess!=1)
        {
            printf("in dj_spit_once, z go back up to tube mouth failed\n");
            return 0;
        } 
    }

    return actSuccess;   

}

int djconvertSpitParam(void * paramIn, void * paramOut)
{
    act_msg_node * pstActMsg = (act_msg_node *)paramIn;
    int actSuccess = 0;

    int isPurify = 0;

    //1, go to target location
    location_layout locLayout;
    location_axis locAxis;
    memcpy(&locLayout,(char*)pstActMsg->paramData,sizeof(location_layout));
    printf("location_type:%d,mx:%d,my:%d,ix:%d,iy:%d\n",
    locLayout.location_type,
    locLayout.indexX,
    locLayout.indexY,
    locLayout.column_x,
    locLayout.row_y);

    int moduleLiquidType = DJ_PURIFY_LIQUID_TYPE;

    if(pstActMsg->msgHead.moduleType == MODULE_DJ_PURIFY)
    {
        isPurify = 1;
    }
    else if(pstActMsg->msgHead.moduleType == MODULE_DJ_QPCR)
    {
        isPurify = 0;
        moduleLiquidType = DJ_QPCR_LIQUID_TYPE;
    }
    else
    {
        printf("in djconvertSuckParam, module type is invalid\n");
        return 0;
    }
    CGpLayout * pstLayout = CGpLayout::get_instance();
    int convertRet = pstLayout->convertToAxisLoc(&locLayout,&locAxis);
    if(convertRet)
    {
        printf("djconvertSuckParam, convert location failed,errorNum:%d\n",convertRet);
    }
    else 
    {
        printf("x=%d,y=%d\n",locAxis.x,locAxis.y);

        actSuccess = djXY_Move(&locAxis,isPurify);
    }
    
    if(actSuccess!=1)
    {
        printf("in djconvertSuckParam, x,y go to target location failed\n");
        return 0;
    }
    unsigned char liquidType = VISCOSITY_LOW;
    int spitVolume = 0;
    char * pstDataBuff = ((char*)pstActMsg->paramData) + sizeof(location_layout);
    //|xylayout|spitVolume|isformulti|remainVolume
    int remainVolume = 1000;
    //read out the liquid type 
    CResource_Manage  * pstResManage = getResourceManage();

    if(pstResManage)
    {
       liquidType = pstResManage->get_curr_liquid_type( moduleLiquidType); 
    }

    //pstDataBuff += sizeof(int);
    memcpy(&spitVolume,pstDataBuff,sizeof(int));

    int isForMulti = 0;
    pstDataBuff += sizeof(int);
    memcpy(&isForMulti,pstDataBuff,sizeof(int));

    pstDataBuff += sizeof(int);
    memcpy(&remainVolume,pstDataBuff,sizeof(int));


    printf("liquidType:%d,volume:%d, isForMulti:%d\n",liquidType,spitVolume,isForMulti);
    if(liquidType >= VISCOSITY_DUMMY || liquidType < VISCOSITY_LOW)
    {
        printf("in dp1_suck, liquidType is %d,change to VISCOSITY_LOW\n");
        liquidType = VISCOSITY_LOW;
    }

    int volumeAir2 = djSuckCtlParam[liquidType].air2;
    int suckBackVolume = 5;

    if(isForMulti)
    {
        volumeAir2 = 0;
        suckBackVolume = 0;
    }

    dynamic_z z_height_pos;
    int zlocValid = pstLayout->getZloc(locLayout.location_type,&z_height_pos);
    if(!zlocValid)
    {
        printf("z location is not valid\n");
        return 0;
    }   
    
    printf("z tube mouth:%d,z max:%d\n",z_height_pos.z_tube_mouth,z_height_pos.z_max);

    int posPre = z_height_pos.z_tube_mouth;

    suck_param * pstSuckParam = (suck_param *)paramOut;
    
    //float liquid_height = 0;
    //convertRet = volumeToHeight_en(remainVolume+spitVolume,TUBE_BOTTOM_SEMISPHERE,&liquid_height); 
    float heightMm = 0;

    int containerTypeDj = getContainerType_Dj(locLayout.location_type);
    
    if(containerTypeDj == -1)
    {
        printf("in djconvertSpitParam, get container type failed\n");
        return 0;
    }
    else
    {
        printf("containerType:%d\n",containerTypeDj);
    }
    

    int converHRet = volumeToHeight_en(remainVolume+spitVolume,containerTypeDj,&heightMm);
    if(converHRet != 0)
    {
        printf("in djconvertSuckParam, calc height through remainvolume failed\n");
        return 0;
    }
    float liquid_height = heightMm;

    int deltaHeightSteps = liquid_height*coeffmmToSteps_DJ_Z;

    int liquidFaceSteps = z_height_pos.z_max - deltaHeightSteps;

    if(liquidFaceSteps<z_height_pos.z_tube_mouth || liquidFaceSteps > z_height_pos.z_max)
    {
        printf("djconvertSpitParam, liquid face height is invalid\n");
        return 0;
    }

    tecan_liquid_param spitParam = {
        .posPre = liquidFaceSteps,
        .posPost = z_height_pos.z_tube_mouth,
        .posMax = z_height_pos.z_max,
        .quantity = spitVolume, // the unit is uL
        .quanSpitAir1 = volumeAir2,//dp1SuckCtlParam[liquidType].air2,
        .quanSuckBack = suckBackVolume,
        .speed = 50,//400 ul/s * 4000inc/1000ul
        .delayAfterSpit = 300, // ms
        .speedGoUp = (int)(400*coeffmmToSteps_DJ_Z), // speed when go up back
        .speedSuckBack = 50,//speed suck back ul/s
    };

    memcpy(paramOut,&spitParam,sizeof(tecan_liquid_param));

    return 1;

}

int djconvertSpitParam_multi(int moduleIn,void * paramIn, void * spitParamOut,void * layoutParamOut)
{
    char * pstMsgData = (char *)paramIn;
    int actSuccess = 0;

    int isPurify = 0;

    //1, parse the first spit hole. x, y
    location_layout * pstLayoutData = (location_layout *)layoutParamOut;
    location_axis locAxis;
    memcpy(pstLayoutData,pstMsgData,sizeof(location_layout));
    printf("location_type:%d,mx:%d,my:%d,ix:%d,iy:%d\n",
    pstLayoutData->location_type,
    pstLayoutData->indexX,
    pstLayoutData->indexY,
    pstLayoutData->column_x,
    pstLayoutData->row_y);

    int moduleLiquidType = DJ_PURIFY_LIQUID_TYPE;

    if(moduleIn == MODULE_DJ_PURIFY)
    {
        isPurify = 1;

    }
    else if(moduleIn == MODULE_DJ_QPCR)
    {
        isPurify = 0;
        moduleLiquidType = DJ_QPCR_LIQUID_TYPE;
    }
    else
    {
        printf("in djconvertSuckParam, module type is invalid\n");
        return 0;
    }    

    unsigned char liquidType = VISCOSITY_LOW;
    int spitVolume = 0;
    char * pstDataBuff = pstMsgData + sizeof(location_layout);
    //|xylayout|spitVolume|isformulti|remainVolume|tiptype
    int remainVolume = 1000;
    //read out the liquid type 
    CResource_Manage  * pstResManage = getResourceManage();

    if(pstResManage)
    {
       liquidType = pstResManage->get_curr_liquid_type( moduleLiquidType); 
    }

    //pstDataBuff += sizeof(int);
    memcpy(&spitVolume,pstDataBuff,sizeof(int));

    int isForMulti = 0;
    pstDataBuff += sizeof(int);
    memcpy(&isForMulti,pstDataBuff,sizeof(int));

    pstDataBuff += sizeof(int);
    memcpy(&remainVolume,pstDataBuff,sizeof(int));
    
    int tipType = 0;
    pstDataBuff += sizeof(int);
    memcpy(&tipType,pstDataBuff,sizeof(int));


    printf("liquidType:%d,volume:%d, isForMulti:%d\n",liquidType,spitVolume,isForMulti);
    if(liquidType >= VISCOSITY_DUMMY || liquidType < VISCOSITY_LOW)
    {
        printf("in dp1_suck, liquidType is %d,change to VISCOSITY_LOW\n");
        liquidType = VISCOSITY_LOW;
    }

    int volumeAir2 = djSuckCtlParam[liquidType].air2;
    int suckBackVolume = 2;

    // if(isForMulti)
    // {
    //     volumeAir2 = 0;
    //     suckBackVolume = 0;
    // }



    dynamic_z z_height_pos;
    CGpLayout * pstLayout = CGpLayout::get_instance();
    int zlocValid = pstLayout->getZloc(pstLayoutData->location_type,&z_height_pos);
    if(!zlocValid)
    {
        printf("z location is not valid\n");
        return 0;
    }   
    
    printf("z tube mouth:%d,z max:%d\n",z_height_pos.z_tube_mouth,z_height_pos.z_max);

    int posPre = z_height_pos.z_tube_mouth;

    //suck_param * pstSuckParam = (suck_param *)spitParamOut;
    float heightMm = 0;

    int containerTypeDj = getContainerType_Dj(pstLayoutData->location_type);
    
    if(containerTypeDj == -1)
    {
        printf("in djconvertSpitParam, get container type failed\n");
        return 0;
    }
    else
    {
        printf("containerType:%d\n",containerTypeDj);
    }
    
    printf("remainVolume:%d,spitVolume:%d\n",remainVolume,spitVolume);
    int converHRet = volumeToHeight_en(remainVolume+spitVolume,containerTypeDj,&heightMm);
    if(converHRet != 0)
    {
        printf("in djconvertSuckParam, calc height through remainvolume failed\n");
        return 0;
    }
    float liquid_height = heightMm;
    //int convertRet = volumeToHeight(remainVolume+spitVolume,TUBE_BOTTOM_CONE,&liquid_height); 
    
    int deltaHeightSteps = liquid_height*coeffmmToSteps_DJ_Z;

    int liquidFaceSteps = z_height_pos.z_max - deltaHeightSteps;

    if(liquidFaceSteps<z_height_pos.z_tube_mouth || liquidFaceSteps > z_height_pos.z_max)
    {
        printf("djconvertSpitParam, liquid face height is invalid\n");
        return 0;
    }

    printf("spitparam, z_max:%d,mouth:%d,deltaHeightSteps:%d,liquid_height:%f\n",
    z_height_pos.z_max,z_height_pos.z_tube_mouth,deltaHeightSteps,liquid_height);

    int posPost = z_height_pos.z_tube_mouth - 1000;
    if(posPost < 0)
    {
       posPost = 0; 
    }

    tecan_liquid_param spitParam = {
        .posPre = liquidFaceSteps,
        .posPost = posPost,
        .posMax = z_height_pos.z_max,
        .quantity = spitVolume, // the unit is uL
        .quanSpitAir1 = volumeAir2,//dp1SuckCtlParam[liquidType].air2,
        .quanSuckBack = suckBackVolume,
        .speed = 50,//400 ul/s * 4000inc/1000ul
        .delayAfterSpit = 300, // ms
        .speedGoUp = (int)(400*coeffmmToSteps_DJ_Z), // speed when go up back
        .speedSuckBack = 50,//speed suck back ul/s
    };

    memcpy(spitParamOut,&spitParam,sizeof(tecan_liquid_param));

    return 1;
}

int dj_spit_multi(void * pstSpitParamIn,void * firstSpitPos,void * holeArr, int dataLen, int purifyCtlIn)
{
    tecan_liquid_param * pstSpitParam = (tecan_liquid_param *)pstSpitParamIn;

    location_layout * pstLayoutData = (location_layout *)firstSpitPos;

    if(dataLen<0)
    {
        printf("dj_spit_multi,param len is invalid\n");
        return 0;
    }
    
    char * holes = (char *)holeArr;
    int holeNum = (dataLen >> 2) + 1; 

    signed char deltaX = 0;
    signed char deltaY = 0;   

    CGpLayout * pstLayout = CGpLayout::get_instance();

    int actSuccess = 0;
    int sidx = SID_DJQ_X;
    int sidy = SID_DJQ_Y;
    int sidz = SID_DJQ_Z;
    int sidPump = SID_DJQ_PUMP;

    int z_tube_mouth = 0;
    float coeffUlToSteps = 12;//32000steps<-->2500ul for pump
    int isPurify = 0;
    if(purifyCtlIn)
    {
        sidx = SID_DJP_X;
        sidy = SID_DJP_Y;
        sidz = SID_DJP_Z;
        if(purifyCtlIn&0x10)
        {
            sidPump = SID_DJP_PUMP_SMALL;
            coeffUlToSteps = 120;//32000steps<-->250ul
        }
        else
        {
            sidPump = SID_DJP_PUMP_BIG;
            coeffUlToSteps = 6;
        }
        isPurify = 1;
         //********************88
        //change the switch here.
    }

    location_layout stLayoutDataReal;

    memcpy(&stLayoutDataReal,pstLayoutData,sizeof(location_layout));
    location_layout stLayoutDataTemp;

    memcpy(&stLayoutDataTemp,&stLayoutDataReal,sizeof(location_layout));

    location_axis axisLoc;
    unsigned short spitVolume = 0;
    int convertRet = 0;
    for(int i=0;i<holeNum;i++)
    {
        if(i>0)
        {
            deltaX = *holes;
            deltaY = *(holes+1);
            memcpy(&spitVolume,holes+2,sizeof(short));

            pstSpitParam->quantity = spitVolume;

            holes += 4;
        }

        stLayoutDataReal.column_x = stLayoutDataTemp.column_x + deltaX;
        stLayoutDataReal.row_y = stLayoutDataTemp.row_y +  deltaY;
        printf("x%d,y%d,v%f,v0:%d\n",stLayoutDataReal.column_x,
        stLayoutDataReal.row_y,pstSpitParam->quantity,spitVolume);
        convertRet = pstLayout->convertToAxisLoc(&stLayoutDataReal,&axisLoc);
        if(convertRet)
        {
            printf("in dj_spit_multi, convert location failed,ix=%d,iy=%d\n",
            stLayoutDataReal.column_x,stLayoutDataReal.row_y);
            actSuccess = 0;
            break;
        }
        else
        {
            printf("in dj_spit_multi, x=%d,y=%d\n",axisLoc.x,axisLoc.y);
        }
        if(i==0)
        {
            actSuccess = djXY_Move(&axisLoc,isPurify);
        }
        else
        {
            actSuccess = djXY_Move_withoutZup(&axisLoc,isPurify);//djXY_Move_withoutZup(&axisLoc,isPurify);//djXY_Move(&axisLoc,isPurify);//djXY_Move_withoutZup(&axisLoc,isPurify);
        }

        if(actSuccess!=1)
        {
            printf("in dj_spit_multi,x,y move failed\n");
            actSuccess = 0;
            break;
        }
        
        if(i == (holeNum-1))
        {
            pstSpitParam->quanSuckBack = 5;// suckBackVolume
            pstSpitParam->quanSpitAir1 = 2;            
            actSuccess = dj_spit_once(pstSpitParam,purifyCtlIn,0);
            //sleep(1);  
        }
        else if(i==0)
        {
            pstSpitParam->quanSuckBack = 2;// suckBackVolume
            pstSpitParam->quanSpitAir1 = 5;
            actSuccess = dj_spit_once(pstSpitParam,purifyCtlIn,0);//0            
        }
        else
        {
            pstSpitParam->quanSpitAir1 = 2;
            pstSpitParam->quanSuckBack = 2;// suckBackVolume
            actSuccess = dj_spit_once(pstSpitParam,purifyCtlIn,0);//0
            //sleep(1);              
        }

        if(!actSuccess)
        {
            printf("in dj_spit_multi, spit once failed\n");
            actSuccess = 0;
            break;
        }
              
    }

    return actSuccess;
}

int dj_module_init(int isPurify)
{
    
    int sidx = SID_DJQ_X;
    int sidy = SID_DJQ_Y;
    int sidz = SID_DJQ_Z;

    int sidjawz = SID_DJQ_JAWZ;

    int sidPump = SID_DJQ_PUMP;

    int sidPump1 = SID_DJP_PUMP_SMALL;

    int actPartNum = 2;

    if(isPurify)
    {
       sidx =  SID_DJP_X;
       sidy =  SID_DJP_Y;
       sidz =  SID_DJP_Z;
       sidPump = SID_DJP_PUMP_BIG;
       actPartNum = 1;
    }

    move_param moveParam[3];
    int actSuccess = 0;
    if(!isPurify)
    {
        moveParam[0].sid = SID_DJQ_JAW;
        moveParam[0].pos = 0;
        moveParam[0].dec_speed = 8000;
        moveParam[0].inc_speed = 8000;
        moveParam[0].speed = 4000;

        actSuccess = uimInitAct_multi(moveParam, 1, 20000);

        if(actSuccess != 1)
        {
            printf("in dj_module_init,jaw ret back failed, actRet:%d\n",actSuccess);
            return 0;
        }
    }

    moveParam[0].sid = sidz;
    moveParam[0].pos = 0;
    moveParam[0].dec_speed = 80000;
    moveParam[0].inc_speed = 80000;
    moveParam[0].speed = 20000;

    moveParam[1].sid = sidjawz;
    moveParam[1].pos = 0;
    moveParam[1].dec_speed = 80000;
    moveParam[1].inc_speed = 80000;
    moveParam[1].speed = 20000;

    actSuccess = uimInitAct_multi(moveParam, actPartNum, 20000);

    if(actSuccess != 1)
    {
        printf("in dj_module_init,z ret back failed, actRet:%d\n",actSuccess);
        return actSuccess;
    }

    moveParam[0].sid = sidx;
    moveParam[0].pos = 0;
    moveParam[0].dec_speed = 80000;
    moveParam[0].inc_speed = 80000;
    moveParam[0].speed = 20000;

    moveParam[1].sid = sidy;
    moveParam[1].pos = 0;
    moveParam[1].dec_speed = 80000;
    moveParam[1].inc_speed = 80000;
    moveParam[1].speed = 20000;
    actSuccess = uimInitAct_multi(moveParam, 2, 20000);

    if(actSuccess != 1)
    {
        printf("dj_module_init, x, y init failed,actRet:%d\n",actSuccess);
        //return actSuccess;
    }

    
    // moveParam[0].sid = sidPump;
    // moveParam[0].pos = 0;
    // moveParam[0].dec_speed = 80000;
    // moveParam[0].inc_speed = 80000;
    // moveParam[0].speed = 20000;

    // moveParam[1].sid = sidPump1;
    // moveParam[1].pos = 0;
    // moveParam[1].dec_speed = 80000;
    // moveParam[1].inc_speed = 80000;
    // moveParam[1].speed = 20000;
    
    // if(isPurify)
    // {
    //     actPartNum = 2;
    // }
    // else
    // {
    //     actPartNum = 1;
    // }
    

    // actSuccess = uimInitAct_multi(moveParam, actPartNum, 20000);

    // if(actSuccess != 1)
    // {
    //     printf("dj_module_init, pump failed,actRet:%d\n",actSuccess);
    // }
    // else
    // {
    //     printf("dj_module_init, pump init ok\n");
    // }
    return actSuccess;
}

int dj_purify_pump_init(void)
{
    int actSuccess = 0;
    move_param moveParam[2];
    moveParam[0].sid = SID_DJP_PUMP_BIG;
    moveParam[0].pos = 0;
    moveParam[0].dec_speed = 80000;
    moveParam[0].inc_speed = 80000;
    moveParam[0].speed = 20000;

    moveParam[1].sid = SID_DJP_PUMP_SMALL;
    moveParam[1].pos = 0;
    moveParam[1].dec_speed = 80000;
    moveParam[1].inc_speed = 80000;
    moveParam[1].speed = 20000;
    

    actSuccess = uimInitAct_multi(moveParam, 2, 20000);

    if(actSuccess != 1)
    {
        printf("dj_purify_pump_init, pump failed,actRet:%d\n",actSuccess);
    }
    else
    {
        printf("dj_purify_pump_init, pump init ok\n");
    }
    return actSuccess;
}

int djQ_transBoard(void * paramIn)
{
    char * pData = (char *)paramIn;

    int actSuccess = 0;

    location_layout locLayoutSrc;
    memcpy(&locLayoutSrc,pData,sizeof(location_layout));

    pData += sizeof(location_layout);
    location_layout locLayoutDst;
    memset(&locLayoutDst,0,sizeof(location_layout));
    locLayoutDst.location_type = -1;
    memcpy(&locLayoutDst,pData,sizeof(location_layout));

    CGpLayout * pstLayout = CGpLayout::get_instance();

    location_axis locAxis;
    int convertRet = 0;
    move_param moveParamArr[2];
    memset(moveParamArr,0,sizeof(move_param)*2);
    int getzRet = 0;
    dynamic_z zloc;

    if(locLayoutSrc.location_type != 0xffff)
    {
        //1, x,y goto src location
        if(locLayoutSrc.location_type == DJ_QPCR_48HOLES)
        {
            locLayoutSrc.location_type = DJ_QPCR_BOARDJAW;
        }

        if(locLayoutSrc.location_type == LOG1_PCR_BOARD)
        {
            locLayoutSrc.location_type = DJ_QPCR_TRANS;
        }
        convertRet = pstLayout->convertToAxisLoc(&locLayoutSrc,&locAxis);

        if(convertRet)
        {
            printf("djQ_transBoard, convert src location failed,errorNum:%d\n",convertRet);
            actSuccess = 0;
        }
        else 
        {
            printf("x=%d,y=%d\n",locAxis.x,locAxis.y);

            actSuccess = djXY_Move(&locAxis,0);
        }

        if(actSuccess != 1)
        {
            printf("djQ_transBoard, x y go to src loc failed\n");
            return 0;
        }
        //2, jaw open
        moveParamArr[0].pos = DJQ_JAW_OPEN_POS;
        moveParamArr[0].dec_speed = 8000;
        moveParamArr[0].inc_speed = 8000;
        moveParamArr[0].speed = 4000;

        moveParamArr[0].sid = SID_DJQ_JAW;

        actSuccess = uimMoveAct_multi(moveParamArr,1,20000);


        if(actSuccess != 1)
        {
            printf("djQ_transBoard, jaw open failed,actRet:%d\n",actSuccess);
            return 0;
        }
        //3, z go down src location 

        getzRet = pstLayout->getZloc(locLayoutSrc.location_type, &zloc);
        if(!getzRet)
        {
            printf("djQ_transBoard, get src z failed\n");
            return 0;        
        }
        moveParamArr[0].pos = zloc.z_tube_mouth;
        moveParamArr[0].dec_speed = 120000;
        moveParamArr[0].inc_speed = 120000;
        moveParamArr[0].speed = 32000;

        moveParamArr[0].sid = SID_DJQ_JAWZ;
        actSuccess = uimMoveAct_multi(moveParamArr,1,20000);


        if(actSuccess != 1)
        {
            printf("djQ_transBoard, z go down to src failed\n");
            return 0;
        }

        //4, jaw close
        moveParamArr[0].pos = DJQ_JAW_CLOSE_POS;
        moveParamArr[0].dec_speed = 8000;
        moveParamArr[0].inc_speed = 8000;
        moveParamArr[0].speed = 4000;

        moveParamArr[0].sid = SID_DJQ_JAW;

        actSuccess = uimMoveAct_multi(moveParamArr,1,20000);

        if(actSuccess != 1)
        {
            printf("djQ_transBoard, jaw close src failed\n");
            return 0;
        }
        
        //4.1,jaw z go up
        moveParamArr[0].pos = 1000;
        moveParamArr[0].dec_speed = 80000;
        moveParamArr[0].inc_speed = 80000;
        moveParamArr[0].speed = 30000;

        moveParamArr[0].sid = SID_DJQ_JAWZ;

        actSuccess = uimMoveAct_multi(moveParamArr,1,20000);

        if(actSuccess != 1)
        {
            printf("djQ_transBoard, jaw z go up failed\n");
            return 0;
        }
    }

    if(locLayoutDst.location_type == 0xffff)
    {
        printf("no need to put at dst location\n");
        return actSuccess;
    }
    else
    {
        printf("locLayoutDst.location_type:%d\n",locLayoutDst.location_type);
    }
        //5, x,y goto dst pos
    if(locLayoutDst.location_type == DJ_QPCR_48HOLES)
    {
        locLayoutDst.location_type = DJ_QPCR_BOARDJAW;
    }
    if(locLayoutDst.location_type == LOG1_PCR_BOARD)
    {
        locLayoutDst.location_type = DJ_QPCR_TRANS;
    }
    convertRet = pstLayout->convertToAxisLoc(&locLayoutDst,&locAxis);

    if(convertRet)
    {
        printf("djQ_transBoard, convert dst location failed,errorNum:%d\n",convertRet);
        actSuccess = 0;
    }
    else 
    {
        printf("x=%d,y=%d\n",locAxis.x,locAxis.y);

        actSuccess = djXY_Move(&locAxis,0);
    }
    if(actSuccess != 1)
    {
        printf("djQ_transBoard, x,y go to dst failed\n");
        return 0;
    }
    //6, z go down
    getzRet = pstLayout->getZloc(locLayoutDst.location_type, &zloc);
    if(!getzRet)
    {
        printf("djQ_transBoard, get dst z failed\n");
        return 0;        
    }

    moveParamArr[0].pos = zloc.z_tube_mouth;
    moveParamArr[0].dec_speed = 120000;
    moveParamArr[0].inc_speed = 120000;
    moveParamArr[0].speed = 32000;

    moveParamArr[0].sid = SID_DJQ_JAWZ;
    actSuccess = uimMoveAct_multi(moveParamArr,1,20000);


    if(actSuccess != 1)
    {
        printf("djQ_transBoard, z go down to dst failed\n");
        return 0;
    }

    //7, jaw  open.
    moveParamArr[0].pos = DJQ_JAW_OPEN_POS;
    moveParamArr[0].dec_speed = 8000;
    moveParamArr[0].inc_speed = 8000;
    moveParamArr[0].speed = 4000;

    moveParamArr[0].sid = SID_DJQ_JAW;

    actSuccess = uimMoveAct_multi(moveParamArr,1,20000);

    if(actSuccess != 1)
    {
        printf("djQ_transBoard, jaw open dst failed\n");
        return 0;
    }

    //8, z go up.
    moveParamArr[0].pos = 0;
    moveParamArr[0].dec_speed = 120000;
    moveParamArr[0].inc_speed = 120000;
    moveParamArr[0].speed = 32000;

    moveParamArr[0].sid = SID_DJQ_JAWZ;
    actSuccess = uimMoveAct_multi(moveParamArr,1,20000);


    if(actSuccess != 1)
    {
        printf("djQ_transBoard, z go up failed\n");
        return 0;
    }



    return actSuccess;
}

int dj_module_move(void * locIn, int isPurifyIn)
{
    int actSuccess = 0;
    location_layout * locLayoutIn = (location_layout *)locIn;

    location_axis locAxis;
    memset(&locAxis,0,sizeof(location_axis));

    CGpLayout * pstLayout = CGpLayout::get_instance();

    int convRet = pstLayout->convertToAxisLoc(locLayoutIn,&locAxis);
    
    if(convRet)
    {
        printf("dj_module_move, convert location failed\n");
        return actSuccess;
    }

    return djXY_Move(&locAxis,isPurifyIn);  

}

float getCoeffPump(int pumpTypeIn)
{
   if(pumpTypeIn == DJ_PUMP_QPCR)
   {
       return 12.8;//32000steps<-->2500ul for pump
   }
   else if(pumpTypeIn == DJ_PUMP_PURIFY_SMALL)
   {
       return 128;//32000steps<-->250ul
   }
   else if(pumpTypeIn == DJ_PUMP_PURIFY_BIG)
   {
       return 6.4; //32000steps<--->5
   }
   else 
   {
       return -1;
   }
}

int dj_pump_ctl(int isSuck, int volume, int pumpType)
{
    int sidPump = -1;
    //int moveDir = 0;

    switch(pumpType)
    {
        case DJ_PUMP_QPCR:
        {
            sidPump = SID_DJQ_PUMP;
        }
        break;
        case DJ_PUMP_PURIFY_BIG:
        {
            sidPump = SID_DJP_PUMP_BIG;

        }
        break;
        case DJ_PUMP_PURIFY_SMALL:
        {
            sidPump = SID_DJP_PUMP_SMALL;

        }
        break;
        default:
        break;
    }

    if(sidPump < 0)
    {
        printf("dj_pump_ctl, pumptype is invalid,%d\n",pumpType);
        return 0;
    }

    float coeffUlToSteps = getCoeffPump(pumpType);//32000steps<-->2500ul for pump
    
    if(coeffUlToSteps < 0)
    {
        printf("dj_pump_ctl, calc coeff failed\n");
        return 0;        
    }
    move_param moveParam;
    memset(&moveParam,0,sizeof(move_param));

    moveParam.dec_speed = 8000;
    moveParam.inc_speed = 8000;
    moveParam.speed = 8000;
    moveParam.sid = sidPump;
    if(isSuck)
    {
        moveParam.dir = 1;
    }
    else
    {
        moveParam.dir = 0;
    } 
    moveParam.pos =   coeffUlToSteps * volume;

    return uimMoveAct_multi_relative(&moveParam,1,20000);
}